package main

import "fmt"

/*
1、go语言中到处是interface，到处都是鸭子类型，并接口是非入侵式的
2、鸭子类型强调的是事务的外部行为，而不是内部的结构
3、在Go中，接口（interface）是方法(method)的集合，是duck-type programming的一种体现，
它允许我们定义一组方法但不实现它们，任何类型只要实现了这些方法，就被认为是实现了该接口。
接口的方法包括方法的名称、输入参数、返回值等信息，但不包括方法的实际实现
接口更重要的作用在于多态实现，它允许程序以多态的方式处理不同类型的值。接口体现了程序设计的多态和高内聚、低耦合的思想。
2、注意事项
（1）接口本身不能创建实例，但是可以指向一个实现了该接口的自定义类型的变量（实例）。
（2）接口中所有的方法都没有方法体，即都是没有实现的方法。
（3）在Go中，一个自定义类型需要将某个接口的所有方法都实现，才能说这个自定义类型实现了该接口。
（4）一个自定义类型只有实现了某个接口，才能将该自定义类型的实例（变量）赋给接口类型。
（5）只要是自定义数据类型就可以实现接口，不仅仅是结构体类型（structs），还包括类型别名（type aliases）、其他接口、自定义类型、变量等。
（6）一个自定义类型可以实现多个接口。
（7）interface 接口不能包含任何变量。
（8）一个接口可以继承多个别的接口，这时如果要实现这个接口必须实现它继承的所有接口的方法。
在低版本的Go编辑器中，一个接口继承其他多个接口时，不允许继承的接口有相同的方法名。
比如A接口继承B、C接口，B、C接口的方法名不能一样。高版本的Go编辑器没有相关问题。
（9）interface类型默认是一个指针（引用类型），如果没有对interface初始化就使用，那么会输出nil。
（10）在Go中，接口的实现是非侵入式，隐式的，不需要显式声明“我实现了这个接口”。
只要一个类型提供了接口中定义的所有方法的具体实现，它就自动成为该接口的一个实现者。
（11）空接口interface{}没有任何方法，是一个能装入任意数量、任意数据类型的数据容器，
我们可以把任何一个变量赋给空接口类型。任意数据类型都能实现空接口，这就和 “空集能被任意集合包含” 一样，空接口能被任意数据类型实现。

*/

/*
一、接口(interface)的定义
type 接口类型名 interface{
    方法名1( 参数列表1 ) 返回值列表1
    方法名2( 参数列表2 ) 返回值列表2
    …
}
*/
//1、定义接口
type showPeople interface {
	getName() //接口中的方法
	getAge()  //接口中的方法
}

// 2、自定义数据类型(可以是strut slice map等等)，也被成为接收者
type peolpe struct {
	name string
	age  int
}

// 3、用自定义的类型实现接口中的所以方法才叫实现接口，
func (s *peolpe) getName() {
	fmt.Println(s.name)
}

func (s *peolpe) getAge() {
	fmt.Println(s.age)
}

func main() {
	//定义infterface变量
	var People showPeople
	// 定义stuct变量
	student1 := peolpe{"jiang", 19}
	People = &student1 //给接口变量赋值由于方法绑定的是指针，给接口变量一个实现了接口的实例
	People.getName()   //调用接口方法
	People.getAge()    //调用接口方法
	//接口变量的复制的另外写法
	var student2 showPeople = &peolpe{"li", 10}
	student2.getName()
	student2.getAge()

}
